import { IncomingMessage, ServerResponse } from "http";
import { UserDao } from "../account_server/dao/UserDao";
import { SystemSettingDao } from "../gm_server/dao/SystemSettingDao";
import { LogServerHelper } from "../log_server/LogServerHelper";
import { Config } from "../src/config/Config";
import { ErrorCode } from "../src/config/ErrorCode";
import { GameConfig } from "../src/config/GameConfig";
import { GoodConfig } from "../src/config/GoodConfig";
import { ServerConfig } from "../src/config/ServerConfig";
import DateUtil from "../src/engine/utils/DateUtil";
import { HaoEncrypt } from "../src/engine/utils/HaoEncrypt";
import { Logger } from "../src/engine/utils/Logger";
import { Md5Helper } from "../src/engine/utils/Md5Helper";
import { WebUtil } from "../src/engine/utils/WebUtil";
import { ResponseModel } from "../src/model/ResponseModel";
import { ServerManager } from "../src/server/ServerManager";
import { ChargeDao } from "./dao/ChargeDao";
const request = require('request');
const crypto = require("crypto");

const routerMap = {
    req_pay: "/req_pay",
    third_alipay_notify_post: "/third_alipay_notify_post"

}

const payVersion = '10'
const mer_no = '6888803037146'
const mer_key = 'tXYkMkROjsFsnhnqoBsYgsT56WPunCDTIx1yFRgA5aTniHHPKPTFfz0C9A2JisNJiogZ8YhOxR4='
const md5key = 'hpEucHLqLdK9oObPLOyWI6ZVhFUX1s8T3PiG0hLdap0+p8X6lYV9FUxUg8ngn6dX0pPBc949NC9TC+UoR5cMtEc84dPN9EkK+DMxX6EUbBNWi6u4aEZy59T/lmqHq/F2oHY4ii79/oJixuz+UKFTiw=='
const sandPubkey = '-----BEGIN CERTIFICATE-----\r\nMIIDJjCCAg6gAwIBAgIGAViVUCVLMA0GCSqGSIb3DQEBCwUAMFQxDTALBgNVBAMT\r\nBFNBTkQxDTALBgNVBAsTBFNBTkQxDTALBgNVBAoTBFNBTkQxCzAJBgNVBAcTAlNI\r\nMQswCQYDVQQIEwJTSDELMAkGA1UEBhMCQ04wHhcNMTYxMTIzMDc1MDA3WhcNMjYx\r\nMTIyMDc1MDA3WjBUMQ0wCwYDVQQDEwRzYW5kMQ0wCwYDVQQLEwRTQU5EMQ0wCwYD\r\nVQQKEwRTQU5EMQswCQYDVQQHEwJTSDELMAkGA1UECBMCU0gxCzAJBgNVBAYTAkNO\r\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyIwo8Jq6XiUSY8cMrDfT\r\nRb65QaWcPH2hITZrei3jgLIdHP3kTQjZueWhp2nQ7H9s6nD99MYSydB4YKZ5qVAo\r\nVxuwRE1fnNKOx8M3npIcr/JKtvCN5TrE1XIUyxWG3F7sPbsafN+7Gwxqh5gT4/u/\r\nzq5busBztvXh+/woiqi3EGQ1WO9+P4AtYA6nr3KoVU7hdO8Aj+6aXMjQQTtDrgH/\r\noiAHkEMJfrQmZ6irdnxzRwQ53D/GzVieAqME/sUMeIBWiy/Uj7d2TVJZkLLlC76l\r\ng6AVo/z9Wl26T0wyttxlCzjfZt1naT3B5IIp8k6lYrOdj3SX1gMD3ej0NGnnrQuu\r\nvwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCd6W65I4SJ2BkH8RsBnZNDpQ7fMTYt\r\nVfQtBctptmEtbSlNz7WKrBFcjsZ6KvsMoUy0ftvaddHKu7t8UhW29C0vWGW00Ihf\r\ndkjGYMWxrNcicX/4KJPjFWwPXw11Vc3NuSlVJrr+eh5OSLHPnpvxoKs4I+55hXS4\r\n4Ch1x2LZ4rLsQ6vrVJz2mnygg2JEeredh74XAMAgAWGZ/Tqn4/QWpjFDggHOF8I9\r\neXddK5yiD+cJ3EcZDYr4LGaaG95XQfvdKNl0igAfFmGd3Sxg5MrFnFJbDsqE0HAF\r\ncrEaCK5rqJVMQdvZEWO4j6c6ZX9WCMfjcXRbZonE3b1DSXCrh1uildk2\r\n-----END CERTIFICATE-----\r\n'


export class PayReqHandler {

    public static instance: PayReqHandler = new PayReqHandler();

    private orderOnlyId: number = 1;


    public init(app) {
        for (const key in routerMap) {
            app.use(routerMap[key], this.onBaseRoot.bind(this))
        }

    }

    private onBaseRoot(req, resp) {
        try {
            let ip: string = WebUtil.getIpByExpressReq(req);
            Logger.log("onBaseRoot=req=", ip, req.baseUrl)
            if (req.baseUrl == routerMap.req_pay) {
                this.checkBody(ip, req, resp, this.on_req_pay.bind(this))
            }
            else if (req.baseUrl == routerMap.third_alipay_notify_post) {
                this.third_alipay_notify_post(req, resp, ip)
            }

        } catch (error) {
            Logger.warn("onBaseRoot error", error);
        }
    }

    private checkBody(ip: string, req, resp, callback: Function) {
        if (req.body) {
            try {
                let jsonObj = JSON.parse(req.body);
                let k: string = jsonObj["k"];
                let data: object = jsonObj["data"]
                if (k == Md5Helper.getMd5_encrypt(JSON.stringify(data))) {
                    callback && callback(req, resp, data, ip);
                }
                else {
                    Logger.warn("收到非法Http请求 key", req.baseUrl, ip, req.body)
                    resp.end();
                }
            } catch (error) {
                Logger.warn("收到非法Http请求body", req.baseUrl, ip, req.body, error)
                resp.end();
            }
        }
        else {
            resp.end();
        }
    }

    private async on_req_pay(req, resp, data: object, ip) {
        Logger.log("on_req_pay===", data)
        resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, "充值未开放")))
        return;
        let goodid: number = data["goodid"]
        let goodConfig: GoodConfig = GoodConfig.configMap.get(goodid)
        if (goodConfig) {
            let userid: number = data["userid"]
            let isExist: boolean = await UserDao.is_user_exist_by_userid(userid)
            if (isExist) {
                let order_id: string = this.productOrder(userid)
                let notify_url = `http://newpay.v81.cn/third_alipay_notify_post`
                let date: Date = new Date()
                let create_time: string = DateUtil.formatDateStr4(date.getTime())
                let order_amt: string = goodConfig.rmb.toFixed(2);
                let cheapUserList: Array<number> = [

                ]
                // if (Config.environment == Config.EnvironmentType.Test) {
                //     order_amt = "0.01"
                // }
                if (cheapUserList.includes(userid)) {
                    order_amt = "0.01"
                }
                let return_url: string = ""
                let create_ip: string = ip.replace(/\./g, '_');
                let pay_extra: string = '{}'
                let accsplit_flag: string = 'NO'
                let sign_type: string = 'MD5'
                let store_id: string = '000000'
                date.setMinutes(date.getMinutes() + 15)
                let expire_time: string = DateUtil.formatDateStr4(date.getTime())
                let goods_name: string = goodConfig.getGooName()
                let product_code: string = '02020004'
                let clear_cycle: string = '3'
                let jump_scheme: string = 'sandcash://scpay'
                let merData = [{ "s": "Android", "n": "大家乐竞技", "id": "com.game.dajialejingji", "sc": "sandcash://scpay" }, { "s": "IOS", "n": "大家乐竞技", "id": "com.game.dajialejingji", "sc": "sandcash://scpay" }]

                let reqData: object = {
                    version: payVersion,
                    mer_no: mer_no,
                    mer_key: mer_key,
                    mer_order_no: order_id,
                    create_time: create_time,
                    order_amt: order_amt,
                    notify_url: notify_url,
                    return_url: return_url,
                    create_ip: create_ip,
                    pay_extra: pay_extra,
                    accsplit_flag: accsplit_flag,
                    sign_type: sign_type,
                    store_id: store_id,
                    expire_time: expire_time,
                    goods_name: goods_name,
                    product_code: product_code,
                    clear_cycle: clear_cycle,
                    jump_scheme: jump_scheme,
                    meta_option: JSON.stringify(merData)
                }

                // 不参与签名属性列表
                let noSigns: Array<string> = ['return_url', 'expire_time', 'goods_name', 'product_code', 'clear_cycle', 'jump_scheme', 'meta_option']
                let paramArr = []
                for (let key in reqData) {
                    let val = reqData[key]
                    if (val === '' || noSigns.indexOf(key) >= 0) {
                        continue
                    }
                    paramArr.push({ key, val })
                }
                paramArr.sort((a, b) => {
                    return a.key > b.key ? 1 : -1
                })
                let strArr = []
                for (let i = 0; i < paramArr.length; i++) {
                    let item = paramArr[i]
                    strArr.push(`${item.key}=${item.val}`)
                }
                strArr.push('key=' + md5key)
                let str = strArr.join('&')
                let sign = crypto.createHash('md5').update(str).digest('hex').toUpperCase();
                reqData["sign"] = sign

                let isDbSuc: boolean = await ChargeDao.insertOrder(order_id, userid, goodConfig.id, goodConfig.rmb, DateUtil.formatDateStr(DateUtil.now()), goodConfig.goodAddType, goodConfig.chargenum)
                if (isDbSuc) {
                    let payinfo: string = JSON.stringify(reqData);
                    resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Suc, "", payinfo)))

                } else {
                    resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, "插入订单失败" + userid)))
                }
            }
            else {
                resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, "不存在用户" + userid)))
            }

        } else {
            resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, "不存在商品" + goodid)))
        }
    }

    private productOrder(userid: number) {
        let orderId: string = DateUtil.formatDateStr4(DateUtil.now()) + "_" + userid + "_" + this.orderOnlyId
        this.orderOnlyId++;
        if (this.orderOnlyId >= 999) {
            this.orderOnlyId = 1;
        }
        return orderId;
    }


    private async third_alipay_notify_post(req, resp, ip: string) {
        Logger.log("third_alipay_notify_post===ip", ip)
        // Logger.log("third_alipay_notify_post==req=", req.body)
        try {
            if (req.body) {
                Logger.log("third_alipay_notify_post==req=", JSON.stringify(req.body))
                let jsonData: object = JSON.parse(req.body.data);
                Logger.log("third_alipay_notify_post==jsonData=", jsonData)
                let isSuccess1: boolean = jsonData["head"]["respCode"] == "000000" || jsonData["head"]["respMsg"] == "成功";
                let isSuccess2: boolean = jsonData["body"]["orderStatus"] == "1";
                let isSuccess = true == isSuccess1 && true == isSuccess2;
                if (true != isSuccess) {
                    Logger.log("订单处理失败", req.body.data);
                    Logger.warn("订单处理失败", req.body.data);
                    return;
                }
                let verify = crypto.createVerify('RSA-SHA1');
                verify.update(req.body.data);
                verify.end();
                let verifyResult = verify.verify(sandPubkey, Buffer.from(req.body.sign, 'base64'));
                if (true != verifyResult) {
                    Logger.log("签名验证失败");
                    Logger.warn("签名验证失败");
                    return;
                }
                let order_id: string = jsonData["body"]["orderCode"]
                let orderObj: object = await ChargeDao.getOrder(order_id)
                if (orderObj) {
                    let isDbSuc: boolean = await ChargeDao.finishOrder(order_id)
                    if (isDbSuc) {
                        resp.send('OK');
                        let userid: number = orderObj["userid"]
                        let goodid: number = orderObj["goodid"]
                        let goodConfig: GoodConfig = GoodConfig.configMap.get(goodid)
                        if (goodConfig.good_type == GoodConfig.GoodType.BeVip) {
                            await UserDao.set_lv(userid, 1)
                            ServerManager.instance.notify_update_lv(userid)
                        }
                        else if (goodConfig.good_type == GoodConfig.GoodType.ChangeVip) {
                            ServerManager.instance.notify_update_invite(userid)
                        }
                        if (goodConfig.goodAddType == GoodConfig.GoodAddType.gems) {
                            let addGems: number = goodConfig.chargenum;
                            if (addGems > 0) {
                                let left_gems: number = await UserDao.addGems(userid, addGems);
                                ServerManager.instance.notify_update_gems(userid)
                                LogServerHelper.log_add_user_gems_history(userid, addGems, left_gems, GameConfig.Gems_History_Reason.Charge, "充值了商品" + goodConfig.id + ",获得了" + addGems + "钻石")

                            }
                        }
                        else if (goodConfig.goodAddType == GoodConfig.GoodAddType.coins) {
                            let addCoins: number = goodConfig.chargenum;
                            if (addCoins) {
                                let left_coins: number = await UserDao.addCoins(userid, addCoins);
                                ServerManager.instance.notify_update_coins(userid)
                                LogServerHelper.log_add_user_coins_history(userid, addCoins, left_coins, GameConfig.Gems_History_Reason.Charge, "充值了商品" + goodConfig.id + ",获得了" + addCoins + "金豆")
                            }
                        }
                        if (goodConfig.good_type == GoodConfig.GoodType.Gem || goodConfig.good_type == GoodConfig.GoodType.Coins) {
                           
                        }
                    } else {
                        Logger.log("更新订单失败==", order_id);
                        Logger.warn("更新订单失败", order_id);
                    }
                } else {
                    Logger.log("订单不存在", order_id);
                    Logger.warn("订单不存在", order_id);
                }
            }
        } catch (error) {
            // Logger.info("third_alipay_notify_post=== error=", error)
            Logger.error("third_alipay_notify_post=== error=", ip, error)
        }
        resp.end("to jhao server suc")
    }

    private async sendDailiGems(userid: number, dailiLevel: number = 1, rmb: number) {
        // let percentArr: Array<number> = [60, 10, 5, 5]
        if (dailiLevel < 3) {//最多有三级代理
            let choushui: string = await SystemSettingDao.get_choushui()
            let percentArr: Array<string> = choushui.split(",")
            let sendPercent: number = parseInt(percentArr[dailiLevel - 1]);
            let userData: object = await UserDao.get_user_data_by_userid(userid)
            let income = userData["income"]
            let qudaodaili = userData["qudaodaili"]
            if (qudaodaili == 1) {
                sendPercent += parseInt(percentArr[3]);
            }
            sendPercent = sendPercent / 100;
            let nowIncome: number = income + rmb * sendPercent * 10000
            await UserDao.update_income(userid, nowIncome)
            let invite = userData["invite"]
            if (invite && invite > 0) {
                dailiLevel++
                this.sendDailiGems(invite, dailiLevel, rmb)
            }
        }
    }



}